﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lucene.Net.Index;
using Lucene.Net.Documents;
using Lucene.Net.Search;
using Lucene.Net.Analysis;
using Lucene.Net.QueryParsers;
using Lucene.Net.Analysis.Standard;
using Winista.Text.HtmlParser.Lex;
using Winista.Text.HtmlParser;
using Winista.Text.HtmlParser.Filters;
using Winista.Text.HtmlParser.Util;
using OgilvyOne.UKNOW.Search;
using Lucene.Net.Store;
using System.Web;
using System.Configuration;
using OgilvyOne.Utility;
using System.Collections;
using System.Text.RegularExpressions;

namespace OgilvyOne.UKNOW.Entity
{
    public class SearchEntity
    {
        /// <summary>
        /// 索引文件路劲
        /// </summary>
        public   string IndexPath { get; set; }
        /// <summary>
        /// 静态文件路径
        /// </summary>
        public  string FilePath { get; set; }
        /// <summary>
        /// 是否创建标识
        /// </summary>
        public  bool IsCreate { get; set; }
        /// <summary>
        /// 搜索关键字
        /// </summary>
        public  string SearchKey { get; set; }
        /// <summary>
        /// 搜索结果数量
        /// </summary>
        public  string ResultCount { get; set; }
        /// <summary>
        /// 搜索结果
        /// </summary>
        public  string SearchResult { get; set; }
        public List<SearchField> SearchFileList { get; set; }

        int icount = 0;
        int lineCount;
        public SearchEntity()
        {
            if (!string.IsNullOrEmpty( ConfigurationSettings.AppSettings["LineCount"]))
            {
                lineCount = int.Parse(ConfigurationSettings.AppSettings["LineCount"]);
            }
             
            SearchFileList = new List<SearchField>();
        }

        /// <summary>
        /// 创建索引IndexWriter对象
        /// </summary>
        /// <returns></returns>
        private    IndexModifier CreateIndexWriter()
        {
            Analyzer analyzer = GetAnalyzer();
            Directory directory = FSDirectory.GetDirectory(IndexPath, true);
            return  new IndexModifier(directory, analyzer, IsCreate);
        }


        /// <summary>
        /// 获取FileInfo对象
        /// </summary>
        /// <returns></returns>
        public  System.IO.FileInfo GetFileInfo()
        {
            return new System.IO.FileInfo(FilePath);
        }

       
        /// <summary>
        /// 获取指定路径下所有文件
        /// </summary>
        /// <returns></returns>
        private   string[] GetFiles()
        {
            System.IO.FileInfo file = GetFileInfo();
            string[] files = System.IO.Directory.GetFiles(file.FullName);//将所有文件的全路径放到files字符数组中
            return files;
        }
       

        /// <summary>
        /// 添加索引文档
        /// </summary>
        /// <param name="files"></param>
        public void AddDocument()
        {
            
            string[] files = GetFiles();
            string html = string.Empty;
            string htmlTitle = string.Empty;
            for (int i = 0; i < files.Length; i++) //根据文件个数使用循环一个一个的索引
            {
                SearchField searchField = new SearchField();
                Document doc = new Document();//创建一个Document,相当于索引数据库中的记录
                if (files[i].EndsWith(".htm") || files[i].EndsWith(".html"))
                {
                    using (System.IO.StreamReader sr = new System.IO.StreamReader(new System.IO.FileInfo(files[i]).FullName, System.Text.Encoding.UTF8))
                    {
                        html = sr.ReadToEnd();
                        htmlTitle = HtmlFileParse.GetTitle(html);
                        html = HtmlFileParse.DelJsStyle(html);
                       // html = HtmlFileParse.Delspace(html);
                        html = html.Replace("<span>", "");
                    }

                    searchField.Path = new System.IO.FileInfo(files[i]).FullName;
                    searchField.FileName = new System.IO.FileInfo(files[i]).Name;
                    searchField.Title = htmlTitle;
                    searchField.Content = HtmlFileParse.HtmltoText(html,SearchKey);
                    SearchFileList.Add(searchField);
                   
                }


            }
        }


       
        /// <summary>
        /// 根据索引字段创建文档
        /// </summary>
        /// <param name="doclist"></param>
        public void BuildIndexFile()
        {
            IndexModifier writer = CreateIndexWriter();
            try
            {
                foreach (SearchField searchField in SearchFileList)
                {
                    writer.AddDocument(GetDocument(searchField));
                }
                writer.Optimize();
            }
            finally
            {
                if (writer != null) writer.Close();
            }
        }

       
        /// <summary>
        /// 创建并返回索引分析器
        /// </summary>
        /// <returns></returns>
        private   Analyzer GetAnalyzer()
        {
            return new StandardAnalyzer();
        }

        public   void Delete(IndexModifier modifier,string field, string url)
        {
            Term term = new Term(field, url);
            modifier.DeleteDocuments(term);//删除    
        }

        /// <summary>
        /// 根据索引字段创建单个文档
        /// </summary>
        /// <param name="searchField"></param>
        /// <returns></returns>
        public   Document GetDocument(SearchField searchField)
        {
            Document document = new Document();
            Field fieldPath = new Field("path", searchField.Path, Field.Store.YES, Field.Index.NO);
            document.Add(fieldPath);
            Field fieldTitle = new Field("title", searchField.Title, Field.Store.YES, Field.Index.TOKENIZED);
            document.Add(fieldTitle);
            Field fieldFileName = new Field("filename", searchField.FileName, Field.Store.YES, Field.Index.TOKENIZED);
            document.Add(fieldFileName);
            if (searchField.ContentLst.Count > 0)
            {
                for (int i = 1; i <= searchField.ContentLst.Count; i++)
                {
                    Field fieldContent = new Field("content" + i.ToString(), searchField.ContentLst[i - 1], Field.Store.YES, Field.Index.TOKENIZED);
                    document.Add(fieldContent);
                }
            }
            else
            {
                Field fieldContent = new Field("content", searchField.Content, Field.Store.YES, Field.Index.TOKENIZED);
                document.Add(fieldContent);
            }
            return document;
        }

        




        /// <summary>
        /// 检索
        /// </summary>
        /// <param name="path_index">索引路径</param>
        /// <param name="key">搜索关键字</param>
        /// <param name="analyzer">分析器</param>
        public void QueryByParagraph()
        {
            
            IndexSearcher searcher = new IndexSearcher(IndexPath);
            Analyzer analyzer = GetAnalyzer();
            BooleanQuery bquery = new BooleanQuery();
            string pathType = string.Empty;
            if (IndexPath.IndexOf("en") > 0)
            {
                pathType = "en";
            }
            else
            {
                pathType = "cn";
            }

            //String[] keys = new String[] { SearchKey, SearchKey };
            string[] keys = SearchKey.Trim().Split(new char[] { ' ', ',', '，', '、','|'}, StringSplitOptions.RemoveEmptyEntries);
            String[] fields = { "content", "title" };
            foreach(string item in keys)
            {
                BooleanClause.Occur[] flags = new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD };
                string[] keyword = { item, item };
                Query query = MultiFieldQueryParser.Parse(keyword, fields, flags, analyzer);
                bquery.Add(query,BooleanClause.Occur.SHOULD);
            }
            DateTime starttime = new DateTime();

            starttime = DateTime.Now;


            TopDocs topDocs = searcher.Search(bquery, 20);
            ScoreDoc[] docs = topDocs.scoreDocs;
            
            DateTime endtime = new DateTime();

            endtime = DateTime.Now;

            TimeSpan aa = endtime - starttime;

            int se = aa.Milliseconds;//查询花费的时间

            ResultCount = docs.Length.ToString();
            StringBuilder sb = new StringBuilder();
          
            for (int i = 0; i < docs.Length; i++)
            {
                icount = 0;
                Document doc = searcher.Doc(docs[i].doc);
                string content = doc.Get("content");
                foreach (string item in keys)
                {
                    Regex r = new Regex("(?<result>"+item+")", RegexOptions.IgnoreCase);
                    Match m = r.Match(content);

                    content=r.Replace(content, "<font color=red>${result}</font>");
                 //  content = content.Replace(item.ToUpper(), "<font color='red'>" + item.ToUpper() + "</font>"); 
                   
                    
                }
                sb.Append("<dl>\n");
                sb.Append("<dt><a href=" + HttpContext.Current.Server.UrlPathEncode("../"+pathType+"/" + doc.Get("filename")) + ">" + doc.Get("title") + "</a></dt>\n");
                PareseContent(doc,sb, content);
            }

            SearchResult = sb.ToString();
            searcher.Close();

        }


        /// <summary>
        /// 检索
        /// </summary>
        /// <param name="path_index">索引路径</param>
        /// <param name="key">搜索关键字</param>
        /// <param name="analyzer">分析器</param>
        public PageTools Query(int pageNo, int rows)
        {
            PageTools pt = null;
            IList dataList = new ArrayList();
            IndexSearcher searcher = new IndexSearcher(IndexPath);
            Analyzer analyzer = GetAnalyzer();
            BooleanQuery bquery = new BooleanQuery();


            //String[] keys = new String[] { SearchKey, SearchKey };
            string[] keys = SearchKey.Trim().Split(new char[] { ' ', ',', '，', '、', '|' }, StringSplitOptions.RemoveEmptyEntries);
            String[] fields = { "content", "title" };
            foreach (string item in keys)
            {
                BooleanClause.Occur[] flags = new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD };
                string[] keyword = { item, item };
                Query query = MultiFieldQueryParser.Parse(keyword, fields, flags, analyzer);
                bquery.Add(query, BooleanClause.Occur.SHOULD);
            }
            DateTime starttime = new DateTime();

            starttime = DateTime.Now;


            TopDocs topDocs = searcher.Search(bquery, pageNo * rows);
            ScoreDoc[] docs = topDocs.scoreDocs;

            DateTime endtime = new DateTime();

            endtime = DateTime.Now;

            TimeSpan aa = endtime - starttime;

            int se = aa.Milliseconds;//查询花费的时间

            ResultCount = docs.Length.ToString();

            for (int i = (pageNo - 1) * rows; i < docs.Length; i++)
            {
                icount = 0;
                SearchField sf = new SearchField();
                Document doc = searcher.Doc(docs[i].doc);
                string content = doc.Get("content");
                sf.Content = doc.Get("content");
                sf.FileName = doc.Get("filename");
                sf.Title = doc.Get("title");
                dataList.Add(sf);

            }
            pt = new PageTools(dataList, pageNo, rows, topDocs.totalHits);
            searcher.Close();
            return pt;

        }


       
        private void   PareseContent(Document doc,StringBuilder sb, string content)
        {
           
            string strResult = string.Empty;
            int startPos = content.LastIndexOf("<p>");
            int count = content.Length-startPos;
            if (icount >= lineCount)
            {
                sb.Append("</dl>\n");
                return;
            }
            if (startPos != -1)
            {
               
                string tmpContent = content.Substring(startPos,count);
                string[] arrkeywords = SearchKey.Trim().Split(new char[] { ' ', ',', '，', '、', '|' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string item in arrkeywords)
                {
                    if (tmpContent.ToUpper().Contains(item.ToUpper()))
                    {
                        int pos=tmpContent.IndexOf("<a");
                        if (pos > 0)
                        {
                            tmpContent = tmpContent.Substring(0, pos - 1);
                        }
                        if (tmpContent.Length > 270)
                        {
                            strResult = content.Substring(startPos, 270) + "...</p>";
                            sb.Append("<dd>" + strResult + "</dd>\n");
                        }
                        else
                        {
                            sb.Append("<dd>" + tmpContent + "</dd>\n");
                        }
                        icount++;
                    }
                }
                
                PareseContent(doc,sb, content.Remove(startPos, count));
            }
           
        }
  
    }
    
 

       
}
